package com.victualler.core.base.repository.impl;


import com.victualler.core.base.dao.BaseDao;
import com.victualler.core.base.repository.IBaseQueryRepository;
import com.victualler.core.common.dto.PageDto;
import com.victualler.core.common.enums.ChecKDataErrorEnum;
import com.victualler.core.common.utils.HQLConverterUtil;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Table;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Map;

/**
 * @Aouthor Guoshichang
 * @Date 9:34 on 2018/6/27.
 * @Function 提供通用查询的基本类
 */
public abstract   class BaseQueryRepositoryImpl<T extends BaseDao,ID extends Serializable> implements IBaseQueryRepository<T,ID> {
    private Class<T> entityClass;
    //提供通用查询的入口
    @PersistenceContext
    protected EntityManager entityManager;


    /**
     * @author Guoshichang
     * @date 11:20 on 2018/6/27.
     * @function 获取entityManager
     */
    public EntityManager getEntityManager() {
        return entityManager;
    }


    /**
     * @author Guoshichang
     * @date 10:42 on 2018/6/27.
     * @param sql 原生sql语句
     * @param params 参数
     * @function 根据sql 查询list结果
     */
    @Override
    public List<T> queryListBySql(String sql, Object[] params){
        try {
            return  HQLConverterUtil.findEOListBySql(sql,params,getEntityClass(),entityManager);
        } catch (Exception e) {
            e.printStackTrace();
            throw ChecKDataErrorEnum.createException(ChecKDataErrorEnum.RUN_ERROR,e.getMessage());
        }
    }

    /**
     * @author Guoshichang
     * @date 10:42 on 2018/6/27.
     * @param sql 原生sql语句
     * @param params 参数
     * @function 根据sql 查询list结果
     */
    @Override
    public List<T> queryListBySql(String sql,Map<String,Object> params){
        try {
            return  HQLConverterUtil.findEOListBySql(sql,params,getEntityClass(),entityManager);
        } catch (Exception e) {
            e.printStackTrace();
            throw ChecKDataErrorEnum.createException(ChecKDataErrorEnum.RUN_ERROR,e.getMessage());
        }
    }

    /**
     * @author Guoshichang
     * @date 10:42 on 2018/6/27.
     * @param sql 原生sql语句
     * @param params 参数
     * @function 根据sql count结果
     */
    @Override
    public long queryCountBySql(String sql, Object[] params){
        try {
            return HQLConverterUtil.getCountBySql(sql,params,entityManager);
        } catch (Exception e) {
            e.printStackTrace();
            throw ChecKDataErrorEnum.createException(ChecKDataErrorEnum.RUN_ERROR,e.getMessage());
        }
    }


    /**
     * @author Guoshichang
     * @date 10:42 on 2018/6/27.
     * @param requestDto 注解配置的查询对象
     * @function 根据sql count结果
     */
    @Override
    public long queryCountByRequestDto(Object requestDto){
        try {
           return  HQLConverterUtil.getCountByRequestVO(requestDto,getEntityClass(),entityManager);
        }catch (Exception e) {
            e.printStackTrace();
            throw ChecKDataErrorEnum.createException(ChecKDataErrorEnum.RUN_ERROR,e.getMessage());
        }
    }

    /**
     * @author Guoshichang
     * @date 10:42 on 2018/6/27.
     * @param requestDto 注解配置的查询对象
     * @function 根据requestDto 查询list结果
     */
    public List<T> queryListByRequestDto(Object requestDto){
        try {
            return  HQLConverterUtil.findEOListByRequestVO(requestDto,getEntityClass(),entityManager);
        }catch (Exception e) {
            e.printStackTrace();
            throw ChecKDataErrorEnum.createException(ChecKDataErrorEnum.RUN_ERROR,e.getMessage());
        }
    }
    /**
     * @author Guoshichang
     * @date 10:42 on 2018/6/27.
     * @param requestDto 注解配置的查询对象
     * @param responseClass 返回参数类型
     * @function 根据requestDto 和自定义的查询结果集获取结果 查询list结果
     */
    @Override
    public <S> List<S> queryListByRequestDto(Object requestDto, Class<S> responseClass){
        try {
            return HQLConverterUtil.findByRequestVO(requestDto, responseClass, entityManager);
        }catch (Exception e) {
           e.printStackTrace();
           throw ChecKDataErrorEnum.createException(ChecKDataErrorEnum.RUN_ERROR,e.getMessage());
        }
    }
    /**
     * @author Guoshichang
     * @date 10:42 on 2018/6/27.
     * @param requestDto 注解配置的查询对象
     * @param responseClass 返回参数类型
     * @function 根据requestDto 和自定义的查询结果集获取结果 查询list结果
     */
    @Override
    public <S> PageDto<S> queryPageByRequestDto(Object requestDto, Class<S> responseClass, int pageNo, int limit){
        try {
            return HQLConverterUtil.findPageByRequestVO(requestDto,responseClass,pageNo,limit,entityManager);
        }catch (Exception e) {
            e.printStackTrace();
            throw ChecKDataErrorEnum.createException(ChecKDataErrorEnum.RUN_ERROR,e.getMessage());
        }
    }


    /**
     * @author Guoshichang
     * @date 10:42 on 2018/6/27.
     * @param requestDto
     * @function 根据requestDto查询 PageDto结果
     */
    @Override
    public PageDto<T> queryEOPageByRequestDto(Object requestDto, int pageNo, int limit) {
        try {
            return HQLConverterUtil.findEOPageByRequestVO(requestDto,getEntityClass(),pageNo,limit,entityManager);
        }catch (Exception e) {
            e.printStackTrace();
            throw ChecKDataErrorEnum.createException(ChecKDataErrorEnum.RUN_ERROR,e.getMessage());
        }
    }

    /**
     * @author Guoshichang
     * @date 10:42 on 2018/6/27.
     * @param sql 原生sql语句
     * @param params 参数
     * @function 根据sql PageDto结果
     */
    @Override
    public PageDto<T> queryPageBySql(String sql, Object[] params, int pageNo, int limit) {
        try {
            return  HQLConverterUtil.findPageBySql(sql,params,getEntityClass(),pageNo,limit,entityManager);
        }catch (Exception e) {
            e.printStackTrace();
            throw ChecKDataErrorEnum.createException(ChecKDataErrorEnum.RUN_ERROR,e.getMessage());
        }
    }

    /**
     * @author Guoshichang
     * @date 10:42 on 2018/6/27.
     * @param sql 原生sql语句
     * @param params 参数
     * @function 根据sql PageDto结果
     */
    @Override
    public <S>PageDto<S> queryPageBySql(String sql, Object[] params,Class<S> responseClass, int pageNo, int limit) {
        try {
            return  HQLConverterUtil.findPageBySql(sql,params,responseClass,pageNo,limit,entityManager);
        }catch (Exception e) {
            e.printStackTrace();
            throw ChecKDataErrorEnum.createException(ChecKDataErrorEnum.RUN_ERROR,e.getMessage());
        }
    }

    /**
     * @author Guoshichang
     * @date 10:42 on 2018/6/27.
     * @param sql 原生sql语句
     * @param params 参数
     * @function 根据sql PageDto结果
     */
    @Override
    public <S>PageDto<S> queryPageBySql(String sql, Map<String,Object> params,Class<S> responseClass, int pageNo, int limit) {
        try {
            return  HQLConverterUtil.findPageBySql(sql,params,responseClass,pageNo,limit,entityManager);
        }catch (Exception e) {
            e.printStackTrace();
            throw ChecKDataErrorEnum.createException(ChecKDataErrorEnum.RUN_ERROR,e.getMessage());
        }
    }

    /**
     * @author Guoshichang
     * @date 11:22 on 2018/6/27.
     * @param entityClass
     * @function 获取某个实体类的表名
     */
    @Override
    public String getTableName(Class<? extends BaseDao> entityClass) {
        //获取枚举
        Table tableAnno= entityClass.getDeclaredAnnotation(Table.class);
        return tableAnno.name();
    }

    /**
     * @author Guoshichang
     * @date 15:31 on 2018/6/27.
     * @function 获取实例类
     */
    @Override
    public Class<T> getEntityClass() {
        if(this.entityClass == null){
            Type genType = getClass().getGenericSuperclass();
            Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
            this.entityClass = (Class) params[0];
        }
        return this.entityClass;
    }


}
